package com.snake.mylibrary.net;

import android.content.Context;

import com.snake.mylibrary.utils.LogUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * OkHttpManager工具类，使用前需要初始化init方法
 */
public class OkHttpManager {
    private static OkHttpClient sOkHttpClient;
    private static OkHttpManager sOkHttpManager = new OkHttpManager();
    private OkHttpManager() {

    }

    public static OkHttpManager getInstance(){
//        if(sOkHttpManager==null){
//            synchronized (OkHttpManager.class){
//                if(sOkHttpManager == null){
//                    sOkHttpManager = new OkHttpManager();
//                }
//            }
//        }
        return sOkHttpManager;
    }

    /**
     * 需要在application调用
     * @param context  上下文
     *
     */
    public  static void init(Context context) {
        File cacheDir = context.getCacheDir();
        int cacheSize = 10*1024*1024;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20,TimeUnit.SECONDS)
                .readTimeout(20,TimeUnit.SECONDS)
                //TODO 缓存策略需要研究
                .cache(new Cache(cacheDir,cacheSize))
                //TODO 每次连接都会产生不同的sessionId，怎么解决？
                .cookieJar(new CookieJar() {
                    private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();
                    @Override
                    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                        cookieStore.put(url,cookies);
                    }

                    @Override
                    public List<Cookie> loadForRequest(HttpUrl url) {
                        List<Cookie> cookies = cookieStore.get(url);
                        return cookies!=null?cookies:new ArrayList<Cookie>();
                    }
                });
        sOkHttpClient = builder.build();
    }

    public BaseResult httpGet(String url){
        Request request = new Request.Builder().url(url).get().build();
        try {
            Response response = sOkHttpClient.newCall(request).execute();
            //public boolean isSuccessful()
            //Returns true if the code is in [200..300),
            LogUtil.e(""+response);
            if(response.isSuccessful()){
                String mResponse = response.body().string();
                LogUtil.e("json: "+ mResponse);
//                Headers headers = response.headers();
//                LogUtil.e("headers->"+headers.toString());
                return new BaseResult(HttpStatus.HTTP_OK,mResponse);
            }else{
                return new BaseResult(HttpStatus.HTTP_FAIL,null);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return new BaseResult(HttpStatus.HTTP_IO_EXCEPTION,null);
        }

    }

    /**键值对数据*/
    public BaseResult httpPost(String url,RequestBody requestBody){
        Request request = new Request.Builder().url(url).post(requestBody).build();
        LogUtil.e("url："+request.url());
        try {
            Response response = sOkHttpClient.newCall(request).execute();
            //public boolean isSuccessful()
            //Returns true if the code is in [200..300),
            if(response.isSuccessful()){
                String mResponse = response.body().string();
                LogUtil.e("json: "+ mResponse);
                return new BaseResult(HttpStatus.HTTP_OK,mResponse);
            }else{
                return new BaseResult(HttpStatus.HTTP_FAIL,null);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return new BaseResult(HttpStatus.HTTP_IO_EXCEPTION,null);
        }
    }

    public BaseResult httpPostString(String url,String param){
        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), param);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        LogUtil.e("url："+request.url());
        try {
            Response response = sOkHttpClient.newCall(request).execute();
            //public boolean isSuccessful()
            //Returns true if the code is in [200..300),
            if(response.isSuccessful()){
                String mResponse = response.body().string();
                LogUtil.e("json: "+ mResponse);
                return new BaseResult(HttpStatus.HTTP_OK,mResponse);
            }else{
                return new BaseResult(HttpStatus.HTTP_FAIL,null);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return new BaseResult(HttpStatus.HTTP_IO_EXCEPTION,null);
        }
    }

    public BaseResult httpPostFile(String url,File file,UploadListener listener){
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        CountingRequestBody countingRequestBody = new CountingRequestBody(requestBody,listener);
        Request request = new Request.Builder().url(url).post(countingRequestBody).build();
        LogUtil.e("url："+request.url());
        try {
            Response response = sOkHttpClient.newCall(request).execute();
            //public boolean isSuccessful()
            //Returns true if the code is in [200..300),
            if(response.isSuccessful()){
                String mResponse = response.body().string();
                LogUtil.e("json: "+ mResponse);
                return new BaseResult(HttpStatus.HTTP_OK,mResponse);
            }else{
                return new BaseResult(HttpStatus.HTTP_FAIL,null);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return new BaseResult(HttpStatus.HTTP_IO_EXCEPTION,null);
        }
    }

    /**
     * 提交表单
     * @param url
     * @param requestBody 需要自己构建
     * @return
     */
    public BaseResult httpPostUploadForm(String url,RequestBody requestBody){
//        RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        LogUtil.e("url："+request.url());
        try {
            Response response = sOkHttpClient.newCall(request).execute();
            //public boolean isSuccessful()
            //Returns true if the code is in [200..300),
            if(response.isSuccessful()){
                String mResponse = response.body().string();
                LogUtil.e("json: "+ mResponse);
                return new BaseResult(HttpStatus.HTTP_OK,mResponse);
            }else{
                return new BaseResult(HttpStatus.HTTP_FAIL,null);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return new BaseResult(HttpStatus.HTTP_IO_EXCEPTION,null);
        }
    }

    /**
     * 下载文件
     * @param url 文件地址
     * @param file 文件的保存路径
     * @return   网络状态
     */
    public HttpStatus httpGetDownload(String url, File file,DownloadListener listener){
        Request request = new Request.Builder().url(url).get().build();
        try {
            Response response = sOkHttpClient.newCall(request).execute();
            //public boolean isSuccessful()
            //Returns true if the code is in [200..300),
            LogUtil.e(""+response);
            if(response.isSuccessful()){
                InputStream is = response.body().byteStream();
                long contentLength = response.body().contentLength();
                long downloadSize = 0L;
                int len = 0;
                byte[] buf = new byte[1024];
                FileOutputStream fos = new FileOutputStream(file);
                while((len=is.read(buf))!= -1){
                    fos.write(buf,0,len);
                    downloadSize+=len;
                    listener.onDownloading(downloadSize,contentLength);
                }
                try{
                    fos.flush();
                    fos.close();
                    is.close();
                }catch(IOException e){}
                LogUtil.e("json: "+ "download success");
                return HttpStatus.HTTP_OK;
            }else{
                return HttpStatus.HTTP_FAIL;
            }

        } catch (IOException e) {
            e.printStackTrace();
            return HttpStatus.HTTP_IO_EXCEPTION;
        }
    }
}
